package com.acme.exchange.network.client;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import com.acme.exchange.network.MessageTransceiver;
import com.acme.exchange.network.proto.Protocol.ExchangeMessage;

public class Client implements Runnable {
	private SocketChannel socketChannel;
	private Selector selector;
	private byte[] serverMessage;
	private BufferedInputStream is;
	private ExchangeMessage serverResponse;
	private MessageTransceiver mt;
	SelectionKey key;

	public Client() {
		serverMessage = new byte[1024];
		is = new BufferedInputStream(System.in);
		mt = new MessageTransceiver();
		try {
			selector = Selector.open();
			socketChannel = SocketChannel.open();
			socketChannel.configureBlocking(true);
			//socketChannel.connect(new InetSocketAddress("192.168.43.61", 1027));
			socketChannel.connect(new InetSocketAddress("localhost", 1027));
			socketChannel.configureBlocking(false);

			key = socketChannel.register(selector, SelectionKey.OP_READ);

		} catch (IOException e) {
			System.out.println("couldn't open a channel");
		}
	}

	public SocketChannel getSocketChannel() {
		return socketChannel;
	}

	public SelectionKey getKey() {
		return key;
	}

	public void run() {
		try {
			while (true) {
				// wait an answer				
				selector.select();
				
				Set<SelectionKey> selectedKeys = selector.selectedKeys();
				Iterator<SelectionKey> iter = selectedKeys.iterator();

				SelectionKey skey;
				while (iter.hasNext()) {
					skey = iter.next();
					if (skey.isReadable()) {

						synchronized (socketChannel) {								
							mt.receive(socketChannel);
						}
						while (mt.hasMessage()) {							
							serverMessage = mt.nextMessage();
							serverResponse = ExchangeMessage
									.parseFrom(serverMessage);
							ServerResponseProcessor.process(serverResponse);
						}
						iter.remove();
					}
				}
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				is.close();
				socketChannel.close();
				selector.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	public static void main(final String args[]) {
		Client client = new Client();
		ClientOrderWriter cow = new ClientOrderWriter(client.getKey());
		new Thread(cow).start();
		client.run();
	}
}
